﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace SimpleModbus
{
    /// <summary>
    /// Modbus协议中的字节序转换类
    /// </summary>
    public class ModbusFormatTool
    {
        /// <summary>
        /// 对16位数据进行格式转换
        /// </summary>
        /// <param name="byteArray">源数据</param>
        /// <param name="start">开始转换数据起点下标</param>
        /// <param name="type">数据格式，即转换规则</param>
        /// <returns></returns>
        public static byte[] Get16ByteArray(byte[] byteArray, int start, DataFormat type)
        {
            //格式校验
            if (byteArray == null || byteArray.Length < start + 2)//start + 2,16位使用2字节存储
            {
                throw new ArgumentException("待转换数据不符合要求！");
            }

            byte[] result = new byte[2];

            // 根据格式类型直接处理
            switch (type)
            {
                case DataFormat.ABCD:
                case DataFormat.BADC:
                    result[0] = byteArray[start + 1];
                    result[1] = byteArray[start];
                    break;
                case DataFormat.CDAB:
                case DataFormat.DCBA:
                    result[0] = byteArray[start];
                    result[1] = byteArray[start + 1];
                    break;
                default:
                    throw new ArgumentException("不支持的数据格式类型！");
            }

            return result;
        }

        /// <summary>
        /// 对32位数据进行格式转换
        /// </summary>
        /// <param name="byteArray">源数据</param>
        /// <param name="start">开始转换数据起点下标</param>
        /// <param name="type">数据格式，即转换规则</param>
        /// <returns></returns>
        public static byte[] Get32ByteArray(byte[] byteArray, int start, DataFormat type)
        {
            //格式校验
            if (byteArray == null || byteArray.Length < start + 4)
            {
                throw new ArgumentException("待转换数据不符合要求！");
            }

            byte[] result = new byte[4];

            switch (type)
            {
                case DataFormat.ABCD:
                    result[0] = byteArray[start + 3];
                    result[1] = byteArray[start + 2];
                    result[2] = byteArray[start + 1];
                    result[3] = byteArray[start];
                    break;
                case DataFormat.BADC:
                    result[0] = byteArray[start + 2];
                    result[1] = byteArray[start + 3];
                    result[2] = byteArray[start];
                    result[3] = byteArray[start + 1];
                    break;
                case DataFormat.CDAB:
                    result[0] = byteArray[start + 1];
                    result[1] = byteArray[start];
                    result[2] = byteArray[start + 3];
                    result[3] = byteArray[start + 2];
                    break;
                case DataFormat.DCBA:
                    Buffer.BlockCopy(byteArray, start, result, 0, 4);
                    break;
                default:
                    throw new ArgumentException("不支持的数据格式类型！");
            }

            return result;

        }

        /// <summary>
        /// 将16位有符号整型转换为字节数组
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static byte[] GetByteArrayFrom16Bit(short value, DataFormat type)
        {
            byte[] res = new byte[2];
            byte[] resTemp = BitConverter.GetBytes(value);

            switch (type)
            {
                case DataFormat.ABCD:
                case DataFormat.BADC:
                    res[0] = resTemp[1];
                    res[1] = resTemp[0];
                    break;
                case DataFormat.CDAB:
                case DataFormat.DCBA:
                    Buffer.BlockCopy(resTemp, 0, res, 0, 2);
                    break;
                default:
                    throw new ArgumentException("不支持的数据格式类型！");
            }

            return res;
        }

        /// <summary>
        /// 将16位无符号整型转换为字节数组
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static byte[] GetByteArrayFrom16Bit(ushort value, DataFormat type)
        {
            byte[] res = new byte[2];
            byte[] resTemp = BitConverter.GetBytes(value);

            switch (type)
            {
                case DataFormat.ABCD:
                case DataFormat.BADC:
                    res[0] = resTemp[1];
                    res[1] = resTemp[0];
                    break;
                case DataFormat.CDAB:
                case DataFormat.DCBA:
                    Buffer.BlockCopy(resTemp, 0, res, 0, 2);
                    break;
                default:
                    throw new ArgumentException("不支持的数据格式类型！");
            }

            return res;
        }

        /// <summary>
        /// 将32位有符号浮点型转换为字节数组
        /// </summary>
        /// <returns></returns>
        public static byte[] GetByteArrayFrom32Bit(float value, DataFormat type)
        {
            byte[] result = new byte[4];
            byte[] resTemp = BitConverter.GetBytes(value);

            switch (type)
            {
                case DataFormat.ABCD:
                    result[0] = resTemp[3];
                    result[1] = resTemp[2];
                    result[2] = resTemp[1];
                    result[3] = resTemp[0];
                    break;
                case DataFormat.BADC:
                    result[0] = resTemp[2];
                    result[1] = resTemp[3];
                    result[2] = resTemp[0];
                    result[3] = resTemp[1];
                    break;
                case DataFormat.CDAB:
                    result[0] = resTemp[1];
                    result[1] = resTemp[0];
                    result[2] = resTemp[3];
                    result[3] = resTemp[2];
                    break;
                case DataFormat.DCBA:
                    Buffer.BlockCopy(resTemp, 0, result, 0, 4);
                    break;
                default:
                    throw new ArgumentException("不支持的数据格式类型！");
            }

            return result;
        }

        /// <summary>
        /// 将32位有符号整型转换为字节数组
        /// </summary>
        /// <returns></returns>
        public static byte[] GetByteArrayFrom32Bit(int value, DataFormat type)
        {
            byte[] result = new byte[4];
            byte[] resTemp = BitConverter.GetBytes(value);

            switch (type)
            {
                case DataFormat.ABCD:
                    result[0] = resTemp[3];
                    result[1] = resTemp[2];
                    result[2] = resTemp[1];
                    result[3] = resTemp[0];
                    break;
                case DataFormat.BADC:
                    result[0] = resTemp[2];
                    result[1] = resTemp[3];
                    result[2] = resTemp[0];
                    result[3] = resTemp[1];
                    break;
                case DataFormat.CDAB:
                    result[0] = resTemp[1];
                    result[1] = resTemp[0];
                    result[2] = resTemp[3];
                    result[3] = resTemp[2];
                    break;
                case DataFormat.DCBA:
                    Buffer.BlockCopy(resTemp, 0, result, 0, 4);
                    break;
                default:
                    throw new ArgumentException("不支持的数据格式类型！");
            }

            return result;
        }

        /// <summary>
        /// 将32位无符号整型转换为字节数组
        /// </summary>
        /// <returns></returns>
        public static byte[] GetByteArrayFrom32Bit(uint value, DataFormat type)
        {
            byte[] result = new byte[4];
            byte[] resTemp = BitConverter.GetBytes(value);

            switch (type)
            {
                case DataFormat.ABCD:
                    result[0] = resTemp[3];
                    result[1] = resTemp[2];
                    result[2] = resTemp[1];
                    result[3] = resTemp[0];
                    break;
                case DataFormat.BADC:
                    result[0] = resTemp[2];
                    result[1] = resTemp[3];
                    result[2] = resTemp[0];
                    result[3] = resTemp[1];
                    break;
                case DataFormat.CDAB:
                    result[0] = resTemp[1];
                    result[1] = resTemp[0];
                    result[2] = resTemp[3];
                    result[3] = resTemp[2];
                    break;
                case DataFormat.DCBA:
                    Buffer.BlockCopy(resTemp, 0, result, 0, 4);
                    break;
                default:
                    throw new ArgumentException("不支持的数据格式类型！");
            }

            return result;
        }
    }
}
